// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

import { ccs } from "../../../../script/util/services";
import { WinBase } from "../../../../script/wins/WinBase";
import * as Util from "../../../../script/mgobe/util";
import global from "../../../../script/mgobe/global";
import { calcFrame, frameSyncState, PlayerState, pushFrames, calResult, hurt } from "../../../../script/mgobe/logic/FrameSyncLogic";
import Room from "../../../../script/mgobe/logic/room";
import { game } from "../../../../script/game/control/game";
import { PlayerData } from "../../../../script/mgobe/model/GameState";
import money from "../../fight/money";
import { colliderType } from "../../../../script/game/gameType";
import { matchType } from "../../../../script/mgobe/ui/matchWin";

const {ccclass, property} = cc._decorator;

export enum battleType {
    //战斗状态
    "ready" = 1,
    "battle",
    "over"
}
export interface battlePlayer {
    id: number | string,
    name: string,
    money: number,
    hp: number,
    attack: number, //攻击的金钱数量
}
export const stateArr = [
    "准备中...",
    "商战中...",
    "结算中..."
]
@ccclass
export default class NewClass extends WinBase{

    @property(cc.Label)
    time: cc.Label = null;

    @property(cc.Label)
    myName: cc.Label = null;

    @property(cc.Label)
    money: cc.Label = null;

    @property(cc.Label)
    battleStateLabel: cc.Label = null;

    @property(cc.Label)
    tipsLabel: cc.Label = null;

    @property(cc.Prefab) 
    moneyPre: cc.Prefab = null;

    @property(cc.Prefab) 
    otherMoneyPre: cc.Prefab = null;
    //计时器
    timer: number = 0;
    // 剩余时间
    leftTime: number = 20;
    //当前状态
    battleState: number = 1;
    lastFrameTime: number = 0;
    //当前提示
    tips: string = '点击金额可修改投资金额';
    //回合结束时间
    gameState: {
        overTime: number,
        state: battleType
    }
    prePool: cc.NodePool = new cc.NodePool();
    otherPrePool: cc.NodePool = new cc.NodePool();
    //投资数组
    battleArr: number[] = [
        10000,
        20000,
        100000,
        1000000,
    ]
    robotArr: number[] = [];
    // 用户信息
    playerInfo: battlePlayer = null;
    //时间
    curTime = {
        m: 3,
        s: 3,
    }
    robot: battlePlayer = null;
    start () {
        //碰撞系统开启
        var manager = cc.director.getCollisionManager();
        manager.enabled = true;
        // manager.enabledDebugDraw = true;
        Util.setBroadcastCallbacks(global.room, this, this as any);
        //调整金钱
        this.fixMoney();
        this.startFrameSync();
        //设置未来时间
        this.setInfo(global.room.roomInfo);
        this.scheduleOnce(() => {
            for(let i = 0; i < 10; i++) {
                let item = cc.instantiate(this.moneyPre);
                this.prePool.put(item);
                let itemOther = cc.instantiate(this.otherMoneyPre);
                this.otherPrePool.put(itemOther);
            }
        }, 1);
        //回收预制体
        this.registerEvent('dismiss', (node: cc.Node, self) => {
            node.setPosition(0, 0);
            if(self) {
                this.prePool.put(node);
            } else {
                this.otherPrePool.put(node);
            }
        })
        this.registerEvent('hurtSelf', (node, self) => {

        })
        this.touchEndEventScale(this.nodes.giveUp, () => {
            let money = game.playerMgr.heroInfo.money * 0.2;
            if(this.battleState === battleType.battle || this.battleState === battleType.ready) {
                ccs.winMgr.showWin("popAlert", {content: "退出比赛吗？将受到商业惩罚：" + ccs.gf.getOmitNum(money), cb: () => {
                    game.playerMgr.calMoney(-money);
                    this.leaveRoom();
                    this._close();
                    if(this._args.matchMode === matchType.rank) {
                        game.playerMgr.reduceRank();
                    }
                    ccs.mainEmitter.emit("upRank");
                }});
            } else {
                this.leaveRoom();
                this._close();
            }
        })
        this.registerEvent('youDie', (id) => {
            this.gameOver(id);
        });
        this.registerEvent('robotAttack', () => {
            hurt(this.playerInfo.id); //玩家受伤
        });
        
        this.registerEvent('attack', (id, money) => {
            if(id !== this.playerInfo.id) {
                //对手攻击
                this.rendomMoney(false, money);
            }
        })
        this.registerEvent('hurtOther', (node, self) => {
            //伤害对手
            this.sendFrame({hp: 1, playerId: frameSyncState.players.find(val => val.id !== this.playerInfo.id).id}, false);
        })
        this.registerEvent('upInfo', (node, self) => {
            //血量更新
            this.updateInfo();
        })
        //设置碰撞区域组件
        this.addCollider();
    }
    //游戏结束
    gameOver(id) {
            if(this.battleState === battleType.over) return;
            if(id === this.playerInfo.id) {
                ccs.winMgr.showWin("popAlert", {content: "你输了，很遗憾"});
                if(this._args.matchMode === matchType.rank) {
                    game.playerMgr.reduceRank();
                }
            } else {
                ccs.winMgr.showWin("popAlert", {content: "你赢了，恭喜"});
                //段位增加
                if(this._args.matchMode === matchType.rank) {
                    game.playerMgr.addRank();
                }
            }
            ccs.mainEmitter.emit("upRank");
            game.gameMgr.saveGame();
            //结束游戏
            this.battleState = battleType.battle;
            this.leftTime = 0;
        
    }
    updateInfo() {
        frameSyncState.players.forEach(val => {
            if(val.id === this.playerInfo.id) {
                this.money.string = ccs.gf.getOmitNum(val.state.money);
                this.setPro(this.nodes.myBar, val.state.hp)
            } else {
                this.setPro(this.nodes.otherBar, val.state.hp)
            }
        })
    }
    setPro(node: cc.Node, hp) {
        node.getComponent(cc.ProgressBar).progress = hp/100;
        node.getChildByName("pro").getComponent(cc.Label).string = hp + "";
    }
    addCollider() {
        let collider = this.nodes.myHome.addComponent(cc.BoxCollider);
        collider.size.width = 500;
        collider.size.height = 50;
        collider.tag = colliderType.myHome;

        let collider2 = this.nodes.other.addComponent(cc.BoxCollider);
        collider2.size.width = 500;
        collider2.size.height = 50;
        collider2.tag = colliderType.otherHome;
        
    }
    getPre(self: boolean): cc.Node{
       let item: cc.Node = null;
       if(self) {
            item = this.prePool.get();
            if(!item) {
                item = cc.instantiate(this.moneyPre);
                this.prePool.put(item);
            }
        } else {
            item = this.otherPrePool.get();
            if(!item) {
                item =  cc.instantiate(this.otherMoneyPre);
                this.otherPrePool.put(item);
            }
        }
       return item;
    }
    // SDK 退出房间
    leaveRoom() {
        Util.appendLog(`正在退出房间`);

        global.room.leaveRoom({}, event => {
            if (event.code === MGOBE.ErrCode.EC_OK) {
                Util.appendLog(`退出房间成功`);
            } else {
                Util.appendLog(`退出房间失败，错误码：${event.code}`);
            }
        });
    }

    // SDK 解散房间
    dismissRoom() {
        Util.appendLog(`正在解散房间`);
        global.room.dismissRoom({}, event => {
            if (event.code === MGOBE.ErrCode.EC_OK) {
                Util.appendLog(`解散房间成功`);
            } else {
                Util.appendLog(`解散房间失败，错误码：${event.code}`);
            }
        });
    }
    fixMoney() {
        this.nodes.moneyManager.children.forEach((val, idx) => {
            this.touchEndEventScale(val, () => {
                if(this.battleState == battleType.ready) {
                    //准备状态
                    ccs.winMgr.showWin('popFixMoney', {
                        maxMoney: game.playerMgr.heroInfo.money,
                        cb: (res) => {
                           this.battleArr[idx] = res;
                           val.children[0].getComponent(cc.Label).string = ccs.gf.getOmitNum(res);
                        }
                    })
                } else if(this.battleState === battleType.battle) {
                    if(game.playerMgr.heroInfo.money < this.battleArr[idx] || game.playerMgr.heroInfo.money <= 0) return;
                    //发送帧消息
                    this.sendFrame({money: this.battleArr[idx]}, true);
                }
            })
        })
    }
    sendFrame(data: object, attack: boolean) {
        
        Util.appendLog(`正在发送帧消息`);
        const sendFramePara: MGOBE.types.SendFramePara = {
            data
        };

        global.room.sendFrame(sendFramePara, event => {
            if (event.code === MGOBE.ErrCode.EC_OK) {
                Util.appendLog(`发送帧消息成功`);
                if(attack) {
                    // @ts-ignore
                    this.rendomMoney(attack, data.money);
                    // @ts-ignore
                    game.playerMgr.heroInfo.money -= data.money;
                }
            } else {
                Util.appendLog(`发送帧消息失败，错误码：${event.code}`);
            }
        });
    }
    attackFrame() {
        //碰撞的时候进行扣血，发送帧消息

    }
    startFrameSync() {
        Util.appendLog(`正在开始帧同步`);
        global.room.startFrameSync({}, event => {
            if (event.code === MGOBE.ErrCode.EC_OK) {
                Util.appendLog(`开始帧同步成功`);
            } else {
                Util.appendLog(`开始帧同步失败，错误码：${event.code}`);
            }
        });
    }
    // SDK 玩家进房广播
    onJoinRoom(event: MGOBE.types.BroadcastEvent<MGOBE.types.JoinRoomBst>) {
        cc.log(event);
        Util.appendLog(`广播：玩家进房`);
    }

    // SDK 玩家退房广播
    onLeaveRoom(event: MGOBE.types.BroadcastEvent<MGOBE.types.LeaveRoomBst>) {
        this.gameOver(123);
        Util.appendLog(`广播：玩家退房`);
    }
    // SDK 房间解散广播
    onDismissRoom(event: MGOBE.types.BroadcastEvent<MGOBE.types.DismissRoomBst>) {
        // this._close();
        Util.appendLog(`广播：房间解散`);
    }
    // SDK 帧同步广播
    onRecvFrame(event: MGOBE.types.BroadcastEvent<MGOBE.types.RecvFrameBst>) {
        pushFrames(event.data.frame);
        calcFrame(event.data.frame);
        this.changeTime(event.data.frame.time);
    }
    
    changeTime(time: number) {
        let distance = 0;
        if(this.lastFrameTime > 0) {
            distance = ccs.gf.getDistanceTime(time, this.lastFrameTime);
        }
        this.lastFrameTime = time;
        if(distance <= 0) {
            return ;
        }
        this.timer += distance;
        //如果超过当前回合时间，计算剩余时间
    }
    //设置信息
    setInfo(data: MGOBE.types.RoomInfo) {
        let { playerList } = data;
        playerList.forEach(val => {
            if(val.name === game.playerMgr.heroInfo.name) {
                this.myName.string = val.name;
                this.money.string = val.customPlayerStatus + "";
                this.playerInfo = Object.assign(val, {money: val.customPlayerStatus, hp: 100, attack: 0});
            } else {
                this.nodes.title.getComponent(cc.Label).string = val.name;
            }
            if(val.isRobot) {
                this.robot = Object.assign(val, {money: val.customPlayerStatus <= 1000? game.playerMgr.heroInfo.money + 10000: val.customPlayerStatus, hp: 100, attack: 0});
                this.robotArr = [this.robot.money* 0.01, this.robot.money * 0.1, this.robot.money * 0.3, this.robot.money * 0.5];
            }
        })
    }
    handlerAttack() {
        if(!this.robot) return ;
        //不定时发送战斗
        if(Math.random() < 0.4) {
            this.robotAttack(Math.floor(Math.random() * 2));
        }
    }
    robotAttack(money: number) {
        if(this.robot.money <= 0 || this.robot.money < money || money < 1) return;
        this.robot.money -= money;
        this.rendomMoney(false, money);
    }

    //生成预制体
    rendomMoney(self: boolean, sendMoney) {
        let item = null;
        let distance = Math.abs(this.nodes.myHome.position.y - this.nodes.other.position.y);
        //如果是自己
        if(self) {
            item = this.getPre(true);
            distance *= 1;
            item.parent = this.nodes.myHome;
            //机器人攻击
            if(this.robot) {
                let money = game.playerMgr.heroInfo.money, robotMoney = 1;
                if(sendMoney <= money * 0.02) {
                    //如果少于0.2 10000 发送200块，说明是试探性
                    robotMoney = this.robotArr[0];
                } else if(sendMoney >= money * 0.1 && sendMoney <= money * 0.3) {
                    robotMoney = this.robotArr[1];
                } else if(sendMoney >= money * 0.5) {
                    robotMoney = this.robotArr[2];
                } else {
                    robotMoney = this.robotArr[Math.floor(Math.random() * 4)];
                }
                this.robotAttack(robotMoney);
            }
        } else {
            item = this.getPre(false);
            distance *= -1;
            item.parent = this.nodes.other;
        }
        item.getComponent(money).setMoney(sendMoney);
        item.setPosition(0, 0);

        //进行移动
        cc.tween(item)
        .by(2, { position: cc.v3(item.position.x, item.position.y + distance) })
        .start();
    }
    update(dt) {
        // this.timer += dt;
        if(this.timer >= 1) {
            if(this.battleState === battleType.battle){
                this.handlerAttack();
            }
            this.leftTime -= this.timer;
            this.timer = 0;
            this.handlerTime();
        }
        
    }
    goBattle() {
        if(this.battleState == battleType.ready) {
            this.leftTime = 20;
        } else {
            this.leftTime = 120;
        }
    }
    handlerTime() {
        if(this.leftTime <= 0) {
            this.leftTime = 0;
            //处理状态
            if(this.battleState == battleType.ready) {
                this.leftTime = 120;
                this.battleState = battleType.battle;
                this.tips = "战斗开始了...";
            } else if(this.battleState == battleType.battle){
                this.leftTime = 10;
                this.battleState = battleType.over;
                this.tips = "战斗结束了，即将在10s内退出战场..."
                let player = calResult();
                this.gameOver(player.id);
            } else {
                //退出战斗
                this.tips = "退出战斗..."
                this.dismissRoom();
                this._close();
            }
        }
        this.tipsLabel.string = this.tips;
        this.battleStateLabel.string = stateArr[this.battleState - 1];
        this.forMateTime();
    }
    forMateTime() {
        //格式化时间
        this.curTime.m = Math.floor(this.leftTime/60);
        this.curTime.s =  Math.trunc(this.leftTime%60);
        this.time.string = "0" + this.curTime.m + ":" +( this.curTime.s < 10? "0" + this.curTime.s: this.curTime.s); 
    }
}

